//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Research.ScientificWorkflow.TridentModel;

namespace Microsoft.Research.ScientificWorkflow.UIDesigner.Controls
{
    /// <summary>
    /// Interaction logic for WorkflowPicker.xaml
    /// </summary>
    public partial class WorkflowPicker : Window
    {
        #region Constructor
        /// <summary>
        /// Initializes a new instance of the workflow picker.
        /// </summary>
        /// <param name="workflowCategories">The workflow categories.</param>
        public WorkflowPicker(Collection<WorkflowCategoryModel> workflowCategories)
        {
            InitializeComponent();
            this.workflowActivityTree.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(WorkflowActivityTree_SelectedItemChanged);
            this.workflowActivityTree.PreviewKeyDown += new KeyEventHandler(WorkflowActivityTree_PreviewKeyDown);
            CreateWfCategoryTree(workflowCategories);
        } 
        #endregion

        #region Properties
        /// <summary>
        /// The selected workflow.
        /// </summary>
        public WorkflowMetadata SelectedWorkflow { get; private set; } 
        #endregion
        
        #region Private methods

        /// <summary>
        /// Create a category tree from the category list given.
        /// </summary>
        /// <param name="workflowCategories">The workflow category list provided.</param>
        private void CreateWfCategoryTree(Collection<WorkflowCategoryModel> workflowCategories)
        {
            // Create the first level of categories in tree.
            for (int categoryCounter = 0; categoryCounter < workflowCategories.Count; categoryCounter++)
            {
                WorkflowCategoryModel objCategory = workflowCategories[categoryCounter];
                TreeViewItem parentNode = this.BuildCategoryNode(objCategory);
                parentNode.GotFocus += new RoutedEventHandler(parentNode_GotFocus);
                this.workflowActivityTree.Items.Add(parentNode);
            }
        }

        /// <summary>
        /// Builds the Category Node fo the given WorkflowCategoryModel
        /// </summary>
        /// <param name="category">ActivityCategoryModel</param>
        /// <returns>TreeViewItem</returns>
        private TreeViewItem BuildCategoryNode(WorkflowCategoryModel category)
        {
            // Create a new category node.
            TreeViewItem categoryParentNode = new TreeViewItem();
            categoryParentNode.Header = category.Label;
            categoryParentNode.DataContext = category;
            categoryParentNode.Style = (Style)TryFindResource(UIDesignerCodeConstants.CATEGORYPICKERTREEITEMSTYLE);
            
            // Iterate through the sub categories and build a tree for them.
            for (int categoryCounter = 0; categoryCounter < category.Categories.Count; categoryCounter++)
            {
                TreeViewItem categoryChild = this.BuildCategoryNode(category.Categories[categoryCounter]);
                categoryParentNode.Items.Add(categoryChild);
            }

            for (int workflowCounter = 0; workflowCounter < category.Workflows.Count; workflowCounter++)
            {
                WorkflowMetadata currentWorkflow = category.Workflows[workflowCounter];
                if (!currentWorkflow.IsDeleted)
                {
                    TreeViewItem workflowItem = BuildWorkflowNode(category.Workflows[workflowCounter]);
                    categoryParentNode.Items.Add(workflowItem);
                }
            }

            // the node created.
            return categoryParentNode;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workflow"></param>
        /// <returns></returns>
        private TreeViewItem BuildWorkflowNode(WorkflowMetadata workflow)
        {
            TreeViewItem workflowNode = new TreeViewItem();
            workflowNode.Header = workflow.DisplayName;
            workflowNode.DataContext = workflow;
            workflowNode.Style = (Style)TryFindResource(UIDesignerCodeConstants.WORKFLOWPICKERTREEITEMSTYLE);
            return workflowNode;
        }

        #endregion

        #region private event handlers.
        /// <summary>
        /// Event handler for the selected item changed event.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args.</param>
        private void WorkflowActivityTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            bool enableOkButton = false;
            if (this.workflowActivityTree.SelectedItem != null)
            {
                // If selected item is a workflow metadata only then enable the Ok button.
                TreeViewItem selectedItem = this.workflowActivityTree.SelectedItem as TreeViewItem;
                WorkflowMetadata selectedWorkflow = selectedItem.DataContext as WorkflowMetadata;
                enableOkButton = (selectedWorkflow != null);
                this.SelectedWorkflow = selectedWorkflow;
            }
            this.btnOk.IsEnabled = enableOkButton;
        }

        /// <summary>
        /// Event handler for the Ok button click.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args.</param>
        private void OkClick(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            this.workflowActivityTree.Items.Clear();
            this.Close();
        }

        /// <summary>
        /// Event handler for the close button.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args.</param>
        private void CloseWindow(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
            this.workflowActivityTree.Items.Clear();
            this.Close();
        }


        /// <summary>
        /// Handles the keydown event on the workflow tree. Expands the node on enter.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WorkflowActivityTree_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                if (this.workflowActivityTree.SelectedItem != null)
                {
                    TreeViewItem selectedItem = this.workflowActivityTree.SelectedItem as TreeViewItem;
                    if (selectedItem.Items.Count > 0)
                    {
                        if (selectedItem.IsExpanded)
                        {
                            selectedItem.IsExpanded = false;
                        }
                        else
                        {
                            selectedItem.IsExpanded = true;
                        }
                        e.Handled = true;
                    }
                }
            }
        }

        /// <summary>
        /// Event handler for the drag of the window.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args.</param>
        private void DragMoveWindow(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void parentNode_GotFocus(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
        }
        #endregion
    }
}
